

import SuperListItem from "./SuperListItem";


const { ccclass, property } = cc._decorator;

@ccclass
export default class SuperScrollView extends cc.ScrollView {

    @property({
        type: cc.Prefab,
        tooltip: 'item模板的预制体',
    })
    pfItemTemplate: cc.Prefab = null;

    @property({
        tooltip: '分帧加载时间间隔',
    })
    duration: number = 1;

    private curIndex: number = 0;
    private itemInfoList: any[] = [];

    private isFrameLoading: boolean = false;
    private isLoadingFinished: boolean = true;

    private cbAfterSetData: Function = null;

    onLoad() {
        this.content.on(cc.Node.EventType.CHILD_ADDED, this.childAdded.bind(this));
        // this.content.on(cc.Node.EventType.CHILD_REMOVED, this.childRemoved.bind(this));
    }

    onEnable() {
        super.onEnable();
        this.node.on("scrolling", this.improveDC, this);
    }

    onDisable() {
        super.onDisable();
        this.node.off("scrolling", this.improveDC, this);
    }

    onDestroy() {
        this.content.off(cc.Node.EventType.CHILD_ADDED, this.childAdded);
        // this.content.off(cc.Node.EventType.CHILD_REMOVED, this.childRemoved);
    }

    //添加节点
    private childAdded(itemNode: cc.Node) {
        this.curIndex++;
        itemNode.name = "item" + this.curIndex;
    }

    //删除节点
    private childRemoved() {

    }

    public scrollToIndex(index: number, seconds: number = 0.2) {
        cc.log("index:", index);
        let childCount = this.content.childrenCount;
        cc.log("childCount:", childCount);
        if (index < 1) {
            cc.log("index 过小");
            index = 1;
        }
        else if (index > childCount) {
            cc.log("index 过大");
            index = childCount;
        }

        let item = this.content.getChildByName('item' + index);
        if (item) {
            let layoutComp: cc.Layout = this.content.getComponent(cc.Layout);
            if (layoutComp) {
                if (layoutComp.type === cc.Layout.Type.VERTICAL) {
                    this.scrollToPercentVertical((childCount - index) / childCount, seconds);
                } else if (layoutComp.type === cc.Layout.Type.HORIZONTAL) {
                    this.scrollToPercentHorizontal((childCount - index) / childCount, seconds);
                } else if (layoutComp.type === cc.Layout.Type.GRID) {

                    if (layoutComp.startAxis === cc.Layout.AxisDirection.HORIZONTAL) {
                        let contentSize = this.content.getContentSize();
                        let itemContentSize = item.getContentSize();
                        // contentSize.width = layoutComp.paddingLeft + layoutComp.paddingRight + itemContentSize.width * n + layoutComp.spacingX *(n-1)
                        let rowEleCount = Math.floor((contentSize.width - layoutComp.paddingLeft - layoutComp.paddingRight + layoutComp.spacingX) / (itemContentSize.width + layoutComp.spacingX))
                        cc.log("每行多少个：", rowEleCount);

                        let hang = Math.ceil(index / rowEleCount);
                        let totalHang = Math.ceil(childCount / rowEleCount);
                        this.scrollToPercentVertical((totalHang - hang) / totalHang, seconds);
                    } else {
                        let contentSize = this.content.getContentSize();
                        let itemContentSize = item.getContentSize();

                        let colEleCount = Math.floor((contentSize.height - layoutComp.paddingTop - layoutComp.paddingBottom + layoutComp.spacingY) / (itemContentSize.height + layoutComp.spacingY))
                        cc.log("每列多少个：", colEleCount);

                        let lie = Math.ceil(index / colEleCount);
                        let totalLie = Math.ceil(childCount / colEleCount);
                        this.scrollToPercentHorizontal((totalLie - lie) / totalLie, seconds);
                    }

                } else {
                    cc.log("cc.Layout.Type不对");
                }
            }
        }
    }

    public improveDC() {
        if (this.content.childrenCount == 0) {
            return;
        }

        let svLeftBottomPoint: cc.Vec2 = this.node.parent.convertToWorldSpaceAR(
            // cc.v2(0,0)
            cc.v2(
                this.node.x - this.node.anchorX * this.node.width,
                this.node.y - this.node.anchorY * this.node.height
            )
        );

        // 求出 ScrollView 可视区域在世界坐标系中的矩形（碰撞盒）
        let svBBoxRect: cc.Rect = cc.rect(svLeftBottomPoint.x, svLeftBottomPoint.y, this.node.width, this.node.height);

        // 遍历 ScrollView Content 内容节点的子节点，对每个子节点的包围盒做和 ScrollView 可视区域包围盒做碰撞判断
        this.content.children.forEach((childNode: cc.Node) => {
            // 如果相交了，那么就显示，否则就隐藏
            let childNodeBBox = childNode.getBoundingBoxToWorld();
            if (childNodeBBox.intersects(svBBoxRect)) {
                if (childNode.opacity === 0) {
                    childNode.opacity = 255;
                }

            } else {
                if (childNode.opacity !== 0) {
                    childNode.opacity = 0;
                }
            }
        });
    }


    public async setData(itemInfoList: any[], isFrameLoading: boolean = false, cb?: Function) {
        if (!this.isLoadingFinished) {
            return;
        }

        this.curIndex = 0;
        this.isLoadingFinished = false;
        this.isFrameLoading = isFrameLoading;
        this.itemInfoList = itemInfoList;
        this.cbAfterSetData = cb;

        this.content.destroyAllChildren();
        if (this.isFrameLoading) {
            await this.executePreFrame(this.getItemGenerator(this.itemInfoList.length), this.duration);
        } else {
            for (let i = 0; i < itemInfoList.length; i++) {
                let item = cc.instantiate(this.pfItemTemplate);
                item.parent = this.content;
                item.getComponent(SuperListItem).setData(itemInfoList[i]);
            }

            this.isLoadingFinished = true;
            this.scheduleOnce(() => {
                this.cbAfterSetData && this.cbAfterSetData();
                this.improveDC();
            });
        }
    }

    //@ts-ignore
    private executePreFrame(generator: Generator, duration: number) {
        return new Promise((resolve, reject) => {
            let gen = generator;
            // 创建执行函数
            let execute = () => {
                // 执行之前，先记录开始时间
                let startTime = new Date().getTime();

                // 然后一直从 Generator 中获取已经拆分好的代码段出来执行
                for (let iter = gen.next(); ; iter = gen.next()) {
                    // 判断是否已经执行完所有 Generator 的小代码段，如果是的话，那么就表示任务完成
                    if (iter == null || iter.done) {
                        //@ts-ignore
                        resolve();
                        return;
                    }

                    // 每执行完一段小代码段，都检查一下是否已经超过我们分配的本帧，这些小代码端的最大可执行时间
                    if (new Date().getTime() - startTime > duration) {
                        // 如果超过了，那么本帧就不在执行，开定时器，让下一帧再执行
                        this.scheduleOnce(() => {
                            execute();
                        });
                        return;
                    }
                }
            };

            // 运行执行函数
            execute();
        });
    }

    private initItem(itemInfo: any) {
        let itemNode = cc.instantiate(this.pfItemTemplate);
        itemNode.parent = this.content;
        itemNode.getComponent(SuperListItem).setData(itemInfo);
    }


    private *getItemGenerator(length: number) {
        for (let i = 0; i < length; i++) {
            yield this.initItem(this.itemInfoList[i]);
        }
        this.isLoadingFinished = true;
        this.scheduleOnce(() => {
            this.cbAfterSetData && this.cbAfterSetData();
            this.improveDC();
        });
    }

    public canInputData(): boolean {
        return this.isLoadingFinished;
    }

    //通过index去获取节点
    public getItem(index: number): cc.Node {
        let item = this.content.getChildByName('item' + index);
        return item || null;
    }

    // update (dt) {}
}
